﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Signage01.dao;
using System.Windows.Input;
using System.Threading;

namespace Signage01.rectangles
{
    public class RectangleResource
    {
        private Resource resource;

        public Resource Resource
        {
            get { return resource; }
            set { resource = value; }
        }
        MainWindow mainWindow;

        // variables for rectangle resize and move
        UIElement source = null;
        bool captured = false;
        bool flagResize = false;
        enum Sides { Left, Right, None };
        Sides side = Sides.None;
        double initialResizeX;
        double finalResizeX;
        MediaElement myMediaElement = null;

        public MediaElement MyMediaElement
        {
            get { return myMediaElement; }
            set { myMediaElement = value; }
        }

        //bool selected = false;

        double initialMoveX;
        double finalMoveX;

        //
        private Rectangle _rectangle;
        private Canvas canvasContainer;
        private Channel channel;
        ContextMenu contextMenu;

        public Rectangle Rectangle
        {
            get { return _rectangle; }
            set { _rectangle = value; }
        }

        private Rectangle rectangleCanvasCampaign;

        public void updateRectangle()
        {
            if (!checkIfInteractsWithOtherRectange2())
            {
                this.Rectangle.Width = this.resource.Duration * 10;
                Canvas.SetLeft(this.Rectangle, this.resource.Offset * 10);
            }
        }


        public RectangleResource(MainWindow mainWindow,Resource resource,Channel channel,bool dragged)
        {
            this.resource = resource;
            this.mainWindow = mainWindow;
            this.canvasContainer = mainWindow.canvasTimeline;
            this.channel = channel;

            this.Rectangle = new Rectangle();

           
           // setResourceDuration();
            

            this.Rectangle.Width = resource.Duration * 10;   
            this.Rectangle.Height = mainWindow.channelVerticalLength;

            this.Rectangle.Stroke = Brushes.Black;
            this.Rectangle.StrokeThickness = 2;

           
            if (dragged)
            {
                //Thread.Sleep(1000);
                int rectangleX = Convert.ToInt32(mainWindow.xDragRectangleTimeline);
                int rectangleY = Convert.ToInt32(Canvas.GetTop(mainWindow.rectangleResourceCurrent));
                Canvas.SetLeft(this.Rectangle,rectangleX );
                Canvas.SetTop(this.Rectangle,rectangleY );

                if (!checkIfInteractsWithOtherRectange2())
                {
                    setResourceThumbnail();
                    
                    
                    this.canvasContainer.Children.Add(this.Rectangle);

                    addEvents();

                    // giving resource object duration based on image and video length, for image duration is 20,
                    // for video duration is equal to the video length

                    //
                    initializeContextMenu();
                    this.Rectangle.ContextMenu = contextMenu;
                    channel.ListResource.Add(this.resource);
                    //Console.WriteLine("dragged true");                    
                    
                }
                else
                {
                    MessageBox.Show("You can't drop resource here, find another position!");
                }
                
            }
            else
            {
                Canvas.SetLeft(this.Rectangle, resource.Offset * 10);
                Canvas.SetTop(this.Rectangle, mainWindow.resourceYPosition);

                setResourceThumbnail();

                this.canvasContainer.Children.Add(this.Rectangle);

                // adding the events for rectangle resize and move
                addEvents();

                // giving resource object duration based on image and video length, for image duration is 20,
                // for video duration is equal to the video length

                //
                initializeContextMenu();
                this.Rectangle.ContextMenu = contextMenu;
                //Console.WriteLine("dragged false");
            }
            
            //prepareResourceinCanvasCampaign();
           
        }

        private void setResourceThumbnail()
        {
            ImageBrush uniformBrush = new ImageBrush();
            if (isResourceImage())
            {
                
                uniformBrush.ImageSource = new BitmapImage(new Uri(System.AppDomain.CurrentDomain.BaseDirectory + "Resources\\" + mainWindow.resourceFileName, UriKind.Absolute));
                //uniformBrush.Stretch = Stretch.None;
                uniformBrush.Viewport = new Rect(0, 0, .3, 1);
    
            }
            else if (isResourceVideo())
            {
                string videoIconPath = System.AppDomain.CurrentDomain.BaseDirectory + "icons\\icon-" + resource.LocalFile.FileExt + ".jpg";
                uniformBrush.ImageSource = new BitmapImage(new Uri(videoIconPath, UriKind.Absolute));
                //float imageWidthRatio = resource.Duration/
                uniformBrush.ViewportUnits = BrushMappingMode.Absolute;
                    
                uniformBrush.Viewport = new Rect(0, 0, mainWindow.channelVerticalLength , mainWindow.channelVerticalLength);
            }
            
            uniformBrush.TileMode = TileMode.None;

            this.Rectangle.Fill = uniformBrush;
        }

        private bool isResourceVideo()
        {
            List<string> listVideoExtention = new List<string>();
            listVideoExtention.Add("flv");
            listVideoExtention.Add("mp4");
            listVideoExtention.Add("avi");            

            foreach (string tempExt in listVideoExtention)
            {
                if (resource.LocalFile.FileExt.EndsWith(tempExt))
                {
                    return true;
                }
            }

            return false;
        }

        private bool isResourceImage()
        {
            List<string> listImageExtention = new List<string>();
            listImageExtention.Add("jpg");
            listImageExtention.Add("jpeg");
            listImageExtention.Add("png");
            listImageExtention.Add("bmp");

            foreach (string tempExt in listImageExtention)
            {
                if (resource.LocalFile.FileExt.EndsWith(tempExt))
                {
                    return true;                    
                }
            }
            return false;
        }

        private void setResourceDuration()
        {

            // checking images 
            if (isResourceImage())
            {
                resource.Duration = 20;
            }
            //
            else if(isResourceVideo())
            {
                myMediaElement = new MediaElement();
                string strURI = System.AppDomain.CurrentDomain.BaseDirectory + "Resources\\" + resource.LocalFile.FileName + "." + resource.LocalFile.FileExt;
                myMediaElement.Source = new Uri(strURI, UriKind.Absolute);
                myMediaElement.LoadedBehavior = MediaState.Manual;
                myMediaElement.UnloadedBehavior = MediaState.Manual;                
                myMediaElement.Pause();
                myMediaElement.MediaOpened += new RoutedEventHandler(media_opened);                    
                
                return;
            }            
        }

        private void media_opened(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("media opened");
            resource.Duration = Convert.ToInt32(myMediaElement.NaturalDuration.TimeSpan.TotalSeconds);
            this.Rectangle.Width = resource.Duration*10;
        }



        private void addEvents()
        {
            this.Rectangle.AddHandler(Canvas.MouseLeftButtonDownEvent, new MouseButtonEventHandler(rectangle_MouseLeftButtonDown_1));
            this.Rectangle.AddHandler(Canvas.MouseLeftButtonUpEvent, new MouseButtonEventHandler(rectangle_MouseLeftButtonUp_1));
            this.Rectangle.AddHandler(Canvas.MouseMoveEvent, new MouseEventHandler(rectangle_MouseMove_1));
            this.Rectangle.AddHandler(Canvas.MouseLeaveEvent, new MouseEventHandler(rectangle_MouseLeave_1));
            //this.Rectangle.AddHandler(Canvas.MouseRightButtonDownEvent, new MouseButtonEventHandler(rectangle_MouseRightButtonDown_1));
        }

        private void showAssociatedPropertyGrid()
        {
            mainWindow.gridResourceProperty.Visibility = Visibility.Visible;
            mainWindow.gridTimelineProperty.Visibility = Visibility.Collapsed;

            mainWindow.spinnerResourceDuration.Value = TimeSpan.FromSeconds(resource.Duration);
            //mainWindow.spinnerResourceDuration.Value = TimeSpan.FromSeconds(mainWindow.rectangleResourceSelected.Resource.Duration);
            mainWindow.spinnerResourceOffset.Value = TimeSpan.FromSeconds(resource.Offset);
            //mainWindow.spinnerResourceOffset.Value = TimeSpan.FromSeconds(mainWindow.rectangleResourceSelected.Resource.Offset);
            mainWindow.textBoxResourceName.Text = resource.LocalFile.FileName + "." + resource.LocalFile.FileExt;
        }

        private void showResourceinCanvasCampaign()
        {
            prepareResourceinCanvasCampaign();            
            mainWindow.campaignCanvas.Children.Clear();
            mainWindow.campaignCanvas.Children.Add(rectangleCanvasCampaign);
        }

        private void prepareResourceinCanvasCampaign()
        {
            if (myMediaElement != null)
            {
                myMediaElement.Stop();
                myMediaElement = null;
            }
            if (isResourceImage())
            {
                mainWindow.stopCampaignTimer();
                rectangleCanvasCampaign = new Rectangle();

                rectangleCanvasCampaign.Width = mainWindow.campaignCanvas.ActualWidth;
                rectangleCanvasCampaign.Height = mainWindow.campaignCanvas.ActualHeight;

                rectangleCanvasCampaign.StrokeThickness = 2;
                rectangleCanvasCampaign.Stroke = Brushes.DarkSalmon;
                ImageBrush backBrush = new ImageBrush();
                backBrush.ImageSource =
                    new BitmapImage(
                        new Uri(System.AppDomain.CurrentDomain.BaseDirectory + "Resources\\" + resource.LocalFile.FileName + "." + resource.LocalFile.FileExt , UriKind.Absolute)
                    );
                //backBrush.Stretch = Stretch.None;
                backBrush.Viewport = new Rect(0, 0, 1, 1);
                backBrush.TileMode = TileMode.None;
                rectangleCanvasCampaign.Fill = backBrush;
                Canvas.SetLeft(rectangleCanvasCampaign, 0);
                Canvas.SetTop(rectangleCanvasCampaign, 0);
                Canvas.SetZIndex(rectangleCanvasCampaign, 0);
                
            }
            else if (isResourceVideo())
            {
                mainWindow.initializeCampaignTimer();
                rectangleCanvasCampaign = new Rectangle();
                rectangleCanvasCampaign.Width = mainWindow.campaignCanvas.ActualWidth;
                rectangleCanvasCampaign.Height = mainWindow.campaignCanvas.ActualHeight;
                if (myMediaElement == null)
                {
                    myMediaElement = new MediaElement();
                    myMediaElement.Source = new Uri(System.AppDomain.CurrentDomain.BaseDirectory + "Resources\\" + resource.LocalFile.FileName + "." + resource.LocalFile.FileExt, UriKind.Absolute);
                    myMediaElement.LoadedBehavior = MediaState.Manual;                    
                }
                myMediaElement.Play();

                VisualBrush myVisualBrush = new VisualBrush();
                mainWindow.mediaElementCanvasCampaign = myMediaElement;

                // myVisualBrush.Viewport = new Rect(0, 0, 0.5, 0.5);
                //myVisualBrush.TileMode = TileMode.Tile;
                myVisualBrush.Visual = myMediaElement;
                rectangleCanvasCampaign.Fill = myVisualBrush;
                Canvas.SetLeft(rectangleCanvasCampaign, 0);
                Canvas.SetTop(rectangleCanvasCampaign, 0);
                Canvas.SetZIndex(rectangleCanvasCampaign, 0);                
            }
            else
            {

            }

        }

        private void rectangle_MouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
        {
            mainWindow.rectangleResourceSelected = this;
            Console.WriteLine("selected resource: " + mainWindow.rectangleResourceSelected.Resource.LocalFile.FileName);
            mainWindow.flagCamapaignOn = false;
            showAssociatedPropertyGrid();
            showResourceinCanvasCampaign();
            

            source = (UIElement)sender;
            Mouse.Capture(source);
            captured = true;
            this.Rectangle.Stroke = Brushes.Orange;
            
            initialMoveX = Canvas.GetLeft(this.Rectangle);            

            finalMoveX = e.GetPosition(canvasContainer).X;            

            mainWindow.Cursor = Cursors.Hand;            
            
            if (flagResize)
            {
                this.Rectangle.Stroke = Brushes.Aqua;
                initialResizeX = Canvas.GetLeft(this.Rectangle);
            }
        }

        private void rectangle_MouseLeftButtonUp_1(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                Console.WriteLine("double clicked");
                return;
            }
            this.Rectangle.Stroke = Brushes.Black;
            captured = false;
            Mouse.Capture(null);
            mainWindow.Cursor = Cursors.Arrow;

            resource.Offset = Convert.ToInt32(Canvas.GetLeft(this.Rectangle) / 10);
            resource.Duration = Convert.ToInt32(this.Rectangle.Width / 10);

            CampaignDAO campaignDAO = CampaignDAO.getSingleTon();
            campaignDAO.updateCampaign(mainWindow.campaignSelected);


            mainWindow.spinnerResourceDuration.Value = TimeSpan.FromSeconds(resource.Duration);
            mainWindow.spinnerResourceOffset.Value = TimeSpan.FromSeconds(resource.Offset);
        }

        private void rectangle_MouseMove_1(object sender, MouseEventArgs e)
        {            
            if (captured)
            {
                // first rectangleon canvas change
                double finalNewMoveX = e.GetPosition(canvasContainer).X;
                

                double newX = initialMoveX + (finalNewMoveX - finalMoveX);
                
                //Canvas.SetLeft(this.Rectangle, newX);                
                canvasContainer.UpdateLayout();
                //y_canvas = y;

                initialMoveX = newX;   
                finalMoveX = finalNewMoveX;

                Console.WriteLine("initial x:" + initialMoveX);
                if (!checkIfInteractsWithOtherRectange() && initialMoveX>=0)
                {
                    Canvas.SetLeft(this.Rectangle, Convert.ToDouble(initialMoveX)); 
                }
            }

            if (checkIfMouseOnRectangleEdge(e))
            {
                mainWindow.Cursor = Cursors.SizeWE;
                flagResize = true;
            }
            else
            {
                mainWindow.Cursor = Cursors.Arrow;
                flagResize = false;
            }

            if (flagResize && captured)
            {
                if(side == Sides.Left)
                {
                    double finalNewResizeX = e.GetPosition(canvasContainer).X;

                    double newX = finalNewResizeX;                    

                    Console.WriteLine("Resize new x: " + newX);

                    //mainWindow.Cursor = Cursors.SizeWE;

                    //screenDivResizeSelected.StartX = Convert.ToInt32(newX);
                    //screenDivResizeSelected.StartY = Convert.ToInt32(newY);

                    if (!checkIfInteractsWithOtherRectange())
                    {
                        Canvas.SetLeft(this.Rectangle, newX);                    
                        this.Rectangle.Width = initialResizeX - finalNewResizeX + this.Rectangle.Width;
                    
                        //y_canvas = y;

                        initialResizeX = newX;                    

                        finalResizeX = finalNewResizeX;                    
                    }
                }
                else if (side == Sides.Right)
                {
                    double finalNewResizeX = e.GetPosition(canvasContainer).X;                    

                    double newX = initialResizeX;


                    if (!checkIfInteractsWithOtherRectange())
                    {
                        Canvas.SetLeft(this.Rectangle, newX);

                        this.Rectangle.Width = finalNewResizeX - initialResizeX;


                        initialResizeX = newX;
                        finalResizeX = finalNewResizeX;
                    }
                    
                }

            }
        }


        private bool checkIfInteractsWithOtherRectange2()
        {
            /*
            while (true)
            {
                Thread.Sleep(1000);
                Console.WriteLine("waiting");
                if (resource.Duration != 0)
                    break;
            }
            */
            foreach (ResourceGraphics resourceGraphicsTemp in channel.ListResourceGraphics)
            {                
                //Rect rectThis = new Rect(initialMoveX,Canvas.GetTop(this.Rectangle),resource.Duration*10,30);
                Rect rectThis = new Rect(this.Resource.Offset * 10, Canvas.GetTop(this.Rectangle), resource.Duration * 10, mainWindow.channelVerticalLength);

                //Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, 30);
                Rect rectOther = new Rect(resourceGraphicsTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceGraphicsTemp.Duration * 10, mainWindow.channelVerticalLength);

                if (rectThis.IntersectsWith(rectOther))
                {
                    return true;
                }
            }

            foreach (Resource resourceTemp in channel.ListResource)
            {
                if (resourceTemp == this.resource)
                {
                    continue;
                }

                //Rect rectThis = new Rect(initialMoveX,Canvas.GetTop(this.Rectangle),resource.Duration*10,30);
                Rect rectThis = new Rect(this.Resource.Offset * 10, Canvas.GetTop(this.Rectangle), resource.Duration * 10, mainWindow.channelVerticalLength);

                //Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, 30);
                Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, mainWindow.channelVerticalLength);

                if (rectThis.IntersectsWith(rectOther))
                {
                    return true;
                }
            }
            return false;
        }

        private bool checkIfInteractsWithOtherRectange()
        {
            foreach (ResourceGraphics resourceGraphicsTemp in channel.ListResourceGraphics)
            {
                
                //Rect rectThis = new Rect(initialMoveX,Canvas.GetTop(this.Rectangle),resource.Duration*10,30);
                Rect rectThis = new Rect(initialMoveX, Canvas.GetTop(this.Rectangle), resource.Duration * 10, mainWindow.channelVerticalLength);

                //Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, 30);
                Rect rectOther = new Rect(resourceGraphicsTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceGraphicsTemp.Duration * 10, mainWindow.channelVerticalLength);

                if (rectThis.IntersectsWith(rectOther))
                {
                    return true;
                }
            }
            foreach (Resource resourceTemp in channel.ListResource)
            {
                if (resourceTemp == this.resource)
                {
                    continue;
                }

                //Rect rectThis = new Rect(initialMoveX,Canvas.GetTop(this.Rectangle),resource.Duration*10,30);
                Rect rectThis = new Rect(initialMoveX, Canvas.GetTop(this.Rectangle), resource.Duration * 10, mainWindow.channelVerticalLength);                

                //Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, 30);
                Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, mainWindow.channelVerticalLength);                

                if (rectThis.IntersectsWith(rectOther))
                {   
                    return true;                  
                }                    
            }
            return false;
        }


        private bool checkIfMouseOnRectangleEdge(MouseEventArgs e)
        {
            // we have to work here only on left and right edge
            double mousePositionX = e.GetPosition(this.Rectangle).X;
            double mousePositionY = e.GetPosition(this.Rectangle).Y;

            double rectangleYTop = Canvas.GetTop(this.Rectangle);
            double rectangleYBottom = Canvas.GetTop(this.Rectangle) + mainWindow.channelVerticalLength;

            //Console.WriteLine(mousePositionX + "," + mousePositionY + "," + rectangleYTop + "," + rectangleYBottom);
            //
            // mouse is near the left edge of the rectangle
            if (mousePositionX < 5 && mousePositionY >= 5 && mousePositionY <= this.Rectangle.Width)
            {
                side = Sides.Left;
                return true;
            }

            // mouse is near the right edge of the rectangle
            else if (mousePositionX <= this.Rectangle.Width && mousePositionX >= this.Rectangle.Width - 5 && mousePositionY >= 5 && mousePositionY <= this.Rectangle.Width)
            {
                side = Sides.Right;
                return true;
            }
            else
            {
                return false;
            }
        }


        private void rectangle_MouseLeave_1(object sender, MouseEventArgs e)
        {
            if (captured == false)
            {
                flagResize = false;
            }
            mainWindow.Cursor = Cursors.Arrow;
        }

        
        //private void rectangle_MouseRightButtonDown_1(object sender, MouseEventArgs e)
        private void initializeContextMenu()
        {           
            contextMenu = new ContextMenu();
            
            MenuItem menuItemCopy = new MenuItem();
            menuItemCopy.Header = "Copy";
            menuItemCopy.Click += new RoutedEventHandler(menuItemCopyClick);
            
            MenuItem menuItemDelete = new MenuItem();
            menuItemDelete.Header = "Delete";
            menuItemDelete.Click += new RoutedEventHandler(menuItemDeleteClick);

            contextMenu.Items.Add(menuItemCopy);
            contextMenu.Items.Add(menuItemDelete);

        }

        private void menuItemCopyClick(Object sender, RoutedEventArgs e)
        {
            Console.WriteLine("copy clicked");
        }

        private void menuItemDeleteClick(Object sender, RoutedEventArgs e)
        {
            //mainWindow.rectangleResourceSelected = this;
            Console.WriteLine("delete clicked");

            MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Are you sure?", "Resource Delete Confirmation", System.Windows.MessageBoxButton.YesNo);
            if (messageBoxResult == MessageBoxResult.Yes)
            {
                this.channel.ListResource.Remove(this.resource);
                mainWindow.listviewTimeline_SelectionChanged_1(null, null);

                CampaignDAO campaignDAO = CampaignDAO.getSingleTon();
                campaignDAO.updateCampaign(mainWindow.campaignSelected);
            }
        }


    }
}
